//
//  QBDropDownMenu.swift
//  QBDropDownMenuDemo
//
//  Created by 乐启榜 on 16/7/25.
//  Copyright © 2016年 乐启榜. All rights reserved.
//

import UIKit

class QBIndexPath: NSObject {
    
    var _column: Int = 0
    var _row: Int = 0
    
    init(column: Int, row: Int){
        _column = column
        _row = row
    }
    
    class func indexPathWithColumn(column: Int, row: Int) -> QBIndexPath {
        
        let indexPath: QBIndexPath = QBIndexPath(column: column, row: row)
        return indexPath
    }
}

@objc protocol QBDropDownMenuDelegate: class {
    
    optional func menu(menu menu: QBDropDownMenu, didSelectedRowAtIndexPath index: QBIndexPath) -> Void
    
}
@objc protocol QBDropDownMenuDataSource: NSObjectProtocol {
    
    func numberOfColumnsInMenu(menu: QBDropDownMenu) ->(Int)
    func menu(menu menu: QBDropDownMenu, numberOfRowsInColumns columns: Int) -> (Int)
    func menu(menu menu: QBDropDownMenu, titleForColumn column: Int) -> (String)
    optional func menu(menu menu: QBDropDownMenu, titleForRowAtIndexPath index: QBIndexPath) ->(String)
}

class QBDropDownMenu: UIView {
    
    private let collectionViewCellID: String = "collectionViewCell"
    private var collectionView: UICollectionView?
    private var backgroundView: UIView = UIView()
    private var numOfMenu: Int = 0
    private var titleButtons: [QBDropDownMenuTitleButton] = []
    private var show: Bool = false
    private var oldSelectedButton: QBDropDownMenuTitleButton?
    private var currentSelectedMenuIndex = 0
    private var clickCount: Int = 0
    private var oldSelectedCell: QBDropDownMenuCollectionViewCell!

    weak var delegate: QBDropDownMenuDelegate?
    weak var dataSource: QBDropDownMenuDataSource?{
        didSet{
            self.numOfMenu = (dataSource?.numberOfColumnsInMenu(self))!
            weak var weakSelf = self
            let width: CGFloat = deviceWidth() / CGFloat(self.numOfMenu)
            self.titleButtons.reserveCapacity(self.numOfMenu)// 数组最小容量 等价于oc中的[NSMutableArray arrayWithCapacity: ]
            
            var lastTitleButton: QBDropDownMenuTitleButton?
            for index in 0..<self.numOfMenu {
                
                let titleStr: String = (dataSource?.menu!(menu: self, titleForRowAtIndexPath: QBIndexPath.indexPathWithColumn(index, row: 0)))!
                let titleButton = QBDropDownMenuTitleButton(maintitle: (self.dataSource?.menu(menu: self, titleForColumn: index))!, subtitle: titleStr)
                self.addSubview(titleButton)
                self.titleButtons.append(titleButton)
                
                titleButton.snp_makeConstraints(closure: { (make) in
                    make.top.bottom.equalTo(weakSelf!)
                    make.width.equalTo(width)
                    
                    if let lastTBTN = lastTitleButton {
                        make.left.equalTo(lastTBTN.snp_right)
                    }else{
                        make.left.equalTo(weakSelf!)
                    }
                })
                
                lastTitleButton = titleButton
                if index != self.numOfMenu - 1 {
                    
                    let rightSeperator = UIView()
                    rightSeperator.backgroundColor = kDropdownMenuSeperatorColor()
                    titleButton.addSubview(rightSeperator)
                    
                    rightSeperator.snp_makeConstraints(closure: { (make) in
                        make.top.right.bottom.equalTo(titleButton)
                        make.width.equalTo(dropDownMenuTitleButtonUIValue().RIGHTSEPERATOR_WIDTH)
                    })
                }
                titleButton.index = index
                titleButton.addTarget(self, action: #selector(titleButtonDidClick(_:)), forControlEvents: .TouchUpInside)
            }
        }
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.userInteractionEnabled = true
        self.currentSelectedMenuIndex = -1
        self.show = false
        
        let flowLayout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
        flowLayout.sectionInset = dropDownMenuCollectionViewUIValue().SECTIONINSETS!
        flowLayout.itemSize = dropDownMenuCollectionViewUIValue().ITEMSIZE!
        flowLayout.minimumLineSpacing = dropDownMenuCollectionViewUIValue().LINESPACING
        flowLayout.minimumInteritemSpacing = dropDownMenuCollectionViewUIValue().INTERITEMSPACING
        
        self.collectionView = UICollectionView(frame: CGRectZero, collectionViewLayout: flowLayout)
        self.collectionView?.collectionViewLayout = flowLayout
        self.collectionView?.registerClass(QBDropDownMenuCollectionViewCell.self, forCellWithReuseIdentifier: collectionViewCellID)
        self.collectionView?.backgroundColor = UIColor.whiteColor()
        self.collectionView?.delegate = self
        self.collectionView?.dataSource = self
        self.collectionView?.autoresizesSubviews = false
        self.autoresizesSubviews = false
        
        self.backgroundView.backgroundColor = UIColor(white: 0.0, alpha: 0.0)
        self.backgroundView.opaque = false
        
        let tapGesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(backgroundDidTap(_: )))
        self.backgroundView.addGestureRecognizer(tapGesture)
        
    }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override var frame: CGRect {
        didSet{
            super.frame = frame
        }
    }
}
// MARK: - Class Methods Action
extension QBDropDownMenu {
    
    private func keyWindow() -> UIWindow{
        return UIApplication.sharedApplication().keyWindow!
    }
    
    private func screenBounds() -> CGRect{
        return self.keyWindow().bounds
    }
    
    // Action
    func backgroundDidTap(sender: UITapGestureRecognizer) {
        weak var weakSelf = self
        let titleButton: QBDropDownMenuTitleButton = self.titleButtons[self.currentSelectedMenuIndex]
        if let collectionView = self.collectionView {
            self.animationTitleButton(titleButton: titleButton, backgrounView: self.backgroundView, collectionView: collectionView, show: false, complete: {
                weakSelf?.show = false
            })
        }
        
    }
    
    func titleButtonDidClick(titleButton: QBDropDownMenuTitleButton) {
        
        weak var weakSelf = self
        self.clickCount += 1
        
        if titleButton.index == self.currentSelectedMenuIndex && self.show == true {
            if let collectionView = self.collectionView {
                
                self.animationTitleButton(titleButton: titleButton, backgrounView: self.backgroundView, collectionView: collectionView, show: false, complete: {
                    weakSelf?.show = false
                })
            }
        } else {
            if let collectionView = self.collectionView {
                self.collectionView?.reloadData()
                self.currentSelectedMenuIndex = titleButton.index
                self.animationTitleButton(titleButton: titleButton, backgrounView: self.backgroundView, collectionView: collectionView, show: true, complete: {
                    weakSelf?.show = true
                })
                
            }
        }
    }
}
// MARK: - UICollectionViewDataSource & UICollectionViewDelegate
extension QBDropDownMenu: UICollectionViewDataSource, UICollectionViewDelegate {
    
    // UICollectionViewDataSource
    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return 1
    }
    
    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return (self.dataSource?.menu(menu: self, numberOfRowsInColumns: self.currentSelectedMenuIndex))!
    }
    
    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(collectionViewCellID, forIndexPath: indexPath) as! QBDropDownMenuCollectionViewCell
        
        cell.containtString = (self.dataSource?.menu!(menu: self, titleForRowAtIndexPath: QBIndexPath.indexPathWithColumn(self.currentSelectedMenuIndex, row: indexPath.row)))!
        
        if cell.containtString == self.titleButtons[self.currentSelectedMenuIndex].subTitle {
            cell.selected = true
            self.oldSelectedCell = cell
        }
        return cell
        
    }
    
    // UICollectionViewDelegate
    func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
        
        self.delegate?.menu!(menu: self, didSelectedRowAtIndexPath: QBIndexPath.indexPathWithColumn(self.currentSelectedMenuIndex, row: indexPath.row))
        self.configMenuSubtitleWithSelectedRow(indexPath.row)
    }
    
    func configMenuSubtitleWithSelectedRow(row: Int){
        
        weak var weakSelf = self
        let button: QBDropDownMenuTitleButton = self.titleButtons[self.currentSelectedMenuIndex]
        let currenSelectedTitleString: String = (self.dataSource?.menu!(menu: self, titleForRowAtIndexPath: QBIndexPath.indexPathWithColumn(self.currentSelectedMenuIndex, row: row)))!
        button.subTitle = currenSelectedTitleString
        if self.oldSelectedCell.containtString != currenSelectedTitleString {
            self.oldSelectedCell.selected = false
            
        }
        if let collectionView = self.collectionView {
            self.animationTitleButton(titleButton: button, backgrounView: self.backgroundView, collectionView: collectionView, show: false, complete: { 
                weakSelf?.show = false
            })
        }
    }
}

// MARK: - Animation Method
extension QBDropDownMenu {
    
    private func animationTitleButton(titleButton titleButton: QBDropDownMenuTitleButton, backgrounView: UIView, collectionView: UICollectionView, show: Bool, complete: () ->Void){
        
        weak var weakSelf = self
        if self.oldSelectedButton == titleButton{
            titleButton.selected = show
        }else{
            titleButton.selected = true
            self.oldSelectedButton?.selected = false
            self.oldSelectedButton = titleButton
        }
        self.animationBackgrounView(backgrounView, show: show) {
            weakSelf?.animationCollectionView(collectionView, show: show, complete: {
                
            })
        }
        complete()
    }
    
    private func animationBackgrounView(backgrounView: UIView, show: Bool, complete: () -> Void){
        
        weak var weakSelf = self
        if show == true {
            if self.clickCount == 1 {
                self.keyWindow().addSubview(backgrounView)
                self.backgroundView.snp_makeConstraints(closure: { (make) in
                    make.top.equalTo((weakSelf?.snp_bottom)!)
                    make.left.right.bottom.equalTo((weakSelf?.keyWindow())!)
                })
                backgrounView.layoutIfNeeded()
            }
            UIView.animateWithDuration(dropDownMenuMenuUIValue().ANIMATION_DURATION, animations: {
                backgrounView.backgroundColor = UIColor(white: 0.0, alpha: 0.3)
                }, completion: { (didFinished) in
            })
        }else{
            UIView.animateWithDuration(dropDownMenuMenuUIValue().ANIMATION_DURATION, animations: {
                backgrounView.backgroundColor = UIColor(white: 0.0, alpha: 0.0)
                }, completion: { (didFinished) in
                    backgrounView.removeFromSuperview()
                    self.clickCount = 0
            })
        }
        complete()
    }
    
    private func animationCollectionView(collection_View: UICollectionView?, show: Bool, complete: () -> Void){
        
        weak var weakSelf = self
        var collectionViewHeight: CGFloat = 0.0
        if show == true {
            if let collectionViewA = collection_View {
                
                var rowCount: CGFloat = 0.0
                let term = collectionViewA.numberOfItemsInSection(0)%dropDownMenuCollectionViewUIValue().VIEW_COLUMNCOUNT
                if term == 0 {
                    rowCount = CGFloat(collectionViewA.numberOfItemsInSection(0)/dropDownMenuCollectionViewUIValue().VIEW_COLUMNCOUNT)
                }else{
                    rowCount = CGFloat(collectionViewA.numberOfItemsInSection(0)/dropDownMenuCollectionViewUIValue().VIEW_COLUMNCOUNT + 1)
                }
                collectionViewHeight = dropDownMenuCollectionViewUIValue().VIEW_TOP_BOTTOM_MARGIN * 2 + dropDownMenuCollectionViewUIValue().CELL_HEIGHT * rowCount + dropDownMenuCollectionViewUIValue().LINESPACING * (rowCount - 1)
                let maxHeight = deviceHeight() - CGRectGetMaxY(self.frame)
                collectionViewHeight = collectionViewHeight > maxHeight ? maxHeight : collectionViewHeight
                
                if self.clickCount == 1 {
                  
                    self.keyWindow().addSubview(collectionViewA)
                    
                    self.collectionView?.snp_remakeConstraints(closure: { (make) in
                        make.top.equalTo((weakSelf?.snp_bottom)!)
                        make.left.right.equalTo((weakSelf?.keyWindow())!)
                    })

                    self.collectionView?.layoutIfNeeded()
                    
                    UIView.animateWithDuration(dropDownMenuMenuUIValue().ANIMATION_DURATION, animations: {
                        collectionViewA.snp_updateConstraints(closure: { (make) in
                            make.height.equalTo(collectionViewHeight)
                        })
                        collectionViewA.superview?.layoutIfNeeded()
                        
                        }, completion: { (didFinished) in
                            
                    })
                } else {
                    
                    UIView.animateWithDuration(dropDownMenuMenuUIValue().ANIMATION_DURATION, animations: {
                        collectionViewA.snp_updateConstraints(closure: { (make) in
                            make.height.equalTo(collectionViewHeight)
                        })
                        collectionViewA.superview?.layoutIfNeeded()
                        
                        }, completion: { (didFinished) in
                            
                    })
                }
            }
          
        } else {
            
            if let collectionViewA = collection_View {
                UIView.animateWithDuration(dropDownMenuMenuUIValue().ANIMATION_DURATION, animations: {
                    collectionViewA.snp_updateConstraints(closure: { (make) in
                        make.height.equalTo(0)
                    })
                    collectionViewA.superview?.layoutIfNeeded()
                    }, completion: { (didFinished) in
                        collectionViewA.removeFromSuperview()
                        self.clickCount = 0
                })
            }
        }
        complete()
    }
}